package rexsee.multimedia;

import java.lang.reflect.Method;

import rexsee.core.utilities.RexseeClazz;
import rexsee.core.utilities.Utilities;
import android.hardware.Camera;
import android.media.MediaRecorder;
import android.media.MediaRecorder.AudioEncoder;
import android.media.MediaRecorder.AudioSource;
import android.media.MediaRecorder.OutputFormat;
import android.media.MediaRecorder.VideoEncoder;
import android.media.MediaRecorder.VideoSource;
import android.view.SurfaceHolder;

public class MediaCaptureArguments {

	public String argumentsText = "";

	public String defaultProfile = "none";

	public int format;
	public int maxDuration;
	public int maxFileSize;

	public int audioSource;
	public int audioEncoder;
	public int audioChannels;
	public int audioBitRate;
	public int audioSamplingRate;

	public int videoSource;
	public int videoEncoder;
	public int videoBitRate;
	public int videoFrameRate;
	public int videoFrameWidth;
	public int videoFrameHeight;
	public int videoOrientationHint;

	public MediaCaptureArguments() {
		setDefault(true);
	}

	public String toString(boolean isVideo) {

		String formatString = (format == OutputFormat.MPEG_4) ? "MPEG_4" : "THREE_GPP";
		String audioSourceString;
		switch (audioSource) {
			case AudioSource.CAMCORDER :
				audioSourceString = "CAMCORDER";
				break;
			case AudioSource.MIC :
				audioSourceString = "MIC";
				break;
			case AudioSource.VOICE_CALL :
				audioSourceString = "VOICE_CALL";
				break;
			case AudioSource.VOICE_DOWNLINK :
				audioSourceString = "VOICE_DOWNLINK";
				break;
			case AudioSource.VOICE_UPLINK :
				audioSourceString = "VOICE_UPLINK";
				break;
			case AudioSource.VOICE_RECOGNITION :
				audioSourceString = "VOICE_RECOGNITION";
				break;
			default :
				audioSourceString = "DEFAULT";
				break;
		}
		String videoSourceString;
		switch (videoSource) {
			case VideoSource.CAMERA :
				videoSourceString = "CAMERA";
				break;
			default :
				videoSourceString = "DEFAULT";
				break;
		}
		String audioEncoderString;
		switch (audioEncoder) {
			case 1 :
				audioEncoderString = "AMR_NB";
				break;
			case 2 :
				audioEncoderString = "AMR_WB";
				break;
			case 3 :
				audioEncoderString = "AAC";
				break;
			case 4 :
				audioEncoderString = "AAC_PLUS";
				break;
			case 5 :
				audioEncoderString = "EAAC_PLUS";
				break;
			default :
				audioEncoderString = "DEFAULT";
				break;
		}
		String videoEncoderString;
		switch (videoEncoder) {
			case VideoEncoder.H263 :
				videoEncoderString = "H263";
				break;
			case VideoEncoder.H264 :
				videoEncoderString = "H264";
				break;
			case VideoEncoder.MPEG_4_SP :
				videoEncoderString = "MPEG_4_SP";
				break;
			default :
				videoEncoderString = "DEFAULT";
				break;
		}

		String rtn = "";

		rtn += "\"defaultProfile\":\"" + defaultProfile + "\"";
		rtn += ",\"format\":\"" + formatString + "\"";
		rtn += ",\"maxDuration\":" + maxDuration;
		rtn += ",\"maxFileSize\":" + maxFileSize;

		rtn += ",\"audioSource\":\"" + audioSourceString + "\"";
		rtn += ",\"audioEncoder\":\"" + audioEncoderString + "\"";
		rtn += ",\"audioBitRate\":" + audioBitRate;
		rtn += ",\"audioChannels\":" + audioChannels;
		rtn += ",\"audioSamplingRate\":" + audioSamplingRate;

		if (isVideo) {
			rtn += ",\"videoSource\":\"" + videoSourceString + "\"";
			rtn += ",\"videoEncoder\":\"" + videoEncoderString + "\"";
			rtn += ",\"videoBitRate\":" + videoBitRate;
			rtn += ",\"videoFrameRate\":" + videoFrameRate;
			rtn += ",\"videoFrameWidth\":" + videoFrameWidth;
			rtn += ",\"videoFrameHeight\":" + videoFrameHeight;
			rtn += ",\"videoOrientationHint\":" + videoOrientationHint; //Since API 9
		}

		return "{" + rtn + "}";

	}
	public MediaCaptureArguments parseArguments(String arguments) {
		if (arguments == null || arguments.equals("")) return this;
		argumentsText = arguments;
		String[] argus = arguments.split(";");
		for (int i = 0; i < argus.length; i++) {
			if (argus[i].indexOf("=") <= 0) continue;
			String key = argus[i].substring(0, argus[i].indexOf("=")).trim();
			String value = argus[i].substring(argus[i].indexOf("=") + 1).trim();
			if (key.equalsIgnoreCase("defaultProfile")) {
				if (value.equalsIgnoreCase("highQuality")) {
					setDefault(true);
					return this;
				} else if (value.equalsIgnoreCase("lowQuality")) {
					setDefault(false);
					return this;
				}
			} else if (key.equalsIgnoreCase("format")) {
				if (value.equalsIgnoreCase("MPEG_4")) format = OutputFormat.MPEG_4;
				else if (value.equalsIgnoreCase("RAW_AMR")) format = OutputFormat.RAW_AMR;
				else format = OutputFormat.THREE_GPP;
			} else if (key.equalsIgnoreCase("maxDuration")) {
				maxDuration = Utilities.getInt(value, -1);
			} else if (key.equalsIgnoreCase("maxFileSize")) {
				maxFileSize = Utilities.getInt(value, -1);
			} else if (key.equalsIgnoreCase("audioSource")) {
				if (value.equalsIgnoreCase("CAMCORDER")) audioSource = AudioSource.CAMCORDER;
				else if (value.equalsIgnoreCase("MIC")) audioSource = AudioSource.MIC;
				else if (value.equalsIgnoreCase("VOICE_CALL")) audioSource = AudioSource.VOICE_CALL;
				else if (value.equalsIgnoreCase("VOICE_DOWNLINK")) audioSource = AudioSource.VOICE_DOWNLINK;
				else if (value.equalsIgnoreCase("VOICE_UPLINK")) audioSource = AudioSource.VOICE_UPLINK;
				else if (value.equalsIgnoreCase("VOICE_RECOGNITION")) audioSource = AudioSource.VOICE_RECOGNITION;
				else audioSource = AudioSource.DEFAULT;
			} else if (key.equalsIgnoreCase("audioEncoder")) {
				if (value.equalsIgnoreCase("AMR_NB")) audioEncoder = AudioEncoder.AMR_NB;
				else if (value.equalsIgnoreCase("AMR_WB")) audioEncoder = 2;
				else if (value.equalsIgnoreCase("AAC")) audioEncoder = 3;
				else if (value.equalsIgnoreCase("AAC_PLUS")) audioEncoder = 4;
				else if (value.equalsIgnoreCase("EAAC_PLUS")) audioEncoder = 5;
				else audioEncoder = AudioEncoder.DEFAULT;
			} else if (key.equalsIgnoreCase("audioChannels")) {
				audioChannels = Utilities.getInt(value, 1);
			} else if (key.equalsIgnoreCase("audioBitRate")) {
				audioBitRate = Utilities.getInt(value, -1);
			} else if (key.equalsIgnoreCase("audioSamplingRate")) {
				audioSamplingRate = Utilities.getInt(value, -1);
			} else if (key.equalsIgnoreCase("videoSource")) {
				if (value.equalsIgnoreCase("CAMERA")) videoSource = VideoSource.CAMERA;
				else videoSource = VideoSource.DEFAULT;
			} else if (key.equalsIgnoreCase("videoEncoder")) {
				if (value.equalsIgnoreCase("H263")) videoEncoder = VideoEncoder.H263;
				else if (value.equalsIgnoreCase("H264")) videoEncoder = VideoEncoder.H264;
				else if (value.equalsIgnoreCase("MPEG_4_SP")) videoEncoder = VideoEncoder.MPEG_4_SP;
				else videoEncoder = VideoEncoder.DEFAULT;
			} else if (key.equalsIgnoreCase("videoBitRate")) {
				videoBitRate = Utilities.getInt(value, -1);
			} else if (key.equalsIgnoreCase("videoFrameRate")) {
				videoFrameRate = Utilities.getInt(value, -1);
			} else if (key.equalsIgnoreCase("videoFrameWidth")) {
				videoFrameWidth = Utilities.getInt(value, 320);
			} else if (key.equalsIgnoreCase("videoFrameHeight")) {
				videoFrameHeight = Utilities.getInt(value, 240);
			} else if (key.equalsIgnoreCase("videoOrientationHint")) { //Since API 9
				if (value.equals("90")) videoOrientationHint = 90;
				else if (value.equals("180")) videoOrientationHint = 180;
				else if (value.equals("270")) videoOrientationHint = 270;
				else videoOrientationHint = 0;
				//MediaRecorder.setOrientationHint(int degrees)
			}
		}
		defaultProfile = "none";
		return this;
	}
	private void setDefault(boolean highQuality) {

		defaultProfile = (highQuality) ? "highQuality" : "lowQuality";

		videoSource = VideoSource.CAMERA;
		audioSource = AudioSource.MIC;
		maxDuration = -1;
		maxFileSize = -1;

		/*
		CamcorderProfile profile = CamcorderProfile.get((highQuality) ? CamcorderProfile.QUALITY_HIGH : CamcorderProfile.QUALITY_LOW);
		format = profile.fileFormat;
		audioEncoder = profile.audioCodec;
		audioBitRate = profile.audioBitRate;
		audioChannels = profile.audioChannels;
		audioSamplingRate = profile.audioSampleRate;
		videoEncoder = profile.videoCodec;
		videoBitRate = profile.videoBitRate;
		videoFrameRate = profile.videoFrameRate;
		videoFrameWidth = profile.videoFrameWidth;
		videoFrameHeight = profile.videoFrameHeight;
		*/

		if (highQuality) {
			format = OutputFormat.MPEG_4;
			audioEncoder = 3; //AAC
			audioBitRate = 96000;
			audioChannels = 2;
			audioSamplingRate = 44100;
			videoEncoder = VideoEncoder.MPEG_4_SP;
			videoBitRate = 10000000;
			videoFrameRate = 30;
			videoFrameWidth = 1280;
			videoFrameHeight = 720;
		} else {
			format = OutputFormat.MPEG_4;
			audioEncoder = AudioEncoder.AMR_NB;
			audioBitRate = 12200;
			audioChannels = 1;
			audioSamplingRate = 8000;
			videoEncoder = VideoEncoder.MPEG_4_SP;
			videoBitRate = 200000;
			videoFrameRate = 15;
			videoFrameWidth = 320;
			videoFrameHeight = 240;
		}

		videoOrientationHint = 0;

	}

	public MediaRecorder getRecorder(Camera camera, SurfaceHolder surfaceHolder, MediaRecorder.OnErrorListener errorListener, MediaRecorder.OnInfoListener infoListener) {

		MediaRecorder recorder = new MediaRecorder();

		recorder.setOnErrorListener(errorListener);
		recorder.setOnInfoListener(infoListener);

		if (maxDuration > 0) recorder.setMaxDuration(maxDuration);
		if (maxFileSize > 0) recorder.setMaxFileSize(maxFileSize);

		if (surfaceHolder != null) {
			if (camera != null) {
				camera.unlock();
				recorder.setCamera(camera);
			}
			recorder.setVideoSource(videoSource);
		}
		recorder.setAudioSource(audioSource);

		recorder.setOutputFormat(format);

		recorder.setAudioEncoder(audioEncoder);

		Method method;

		try {
			//recorder.setAudioChannels(audioChannels);
			method = RexseeClazz.getMethod(MediaRecorder.class, "setAudioChannels");
			if (method != null) method.invoke(recorder, new Object[]{audioChannels});

			//if (audioBitRate > 0) recorder.setAudioEncodingBitRate(audioBitRate);
			method = RexseeClazz.getMethod(MediaRecorder.class, "setAudioEncodingBitRate");
			if (method != null) method.invoke(recorder, new Object[]{audioBitRate});

			//if (audioSamplingRate > 0) recorder.setAudioSamplingRate(audioSamplingRate);
			method = RexseeClazz.getMethod(MediaRecorder.class, "setAudioSamplingRate");
			if (method != null) method.invoke(recorder, new Object[]{audioSamplingRate});
		} catch (Exception e) {
		}

		if (surfaceHolder != null) {

			recorder.setVideoEncoder(videoEncoder);
			try {
				//if (videoBitRate > 0) recorder.setVideoEncodingBitRate(videoBitRate);
				method = RexseeClazz.getMethod(MediaRecorder.class, "setVideoEncodingBitRate");
				if (method != null) method.invoke(recorder, new Object[]{videoBitRate});
			} catch (Exception e) {
			}

			if (videoFrameRate > 0) recorder.setVideoFrameRate(videoFrameRate);
			recorder.setVideoSize(videoFrameWidth, videoFrameHeight);
			//recorder.setOrientationHint(videoOrientationHint);
			recorder.setPreviewDisplay(surfaceHolder.getSurface());
		}

		return recorder;

	}

}
